package com.example.administrator.anyview.my_views;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.example.administrator.anyview.R;

import java.util.Calendar;

public class AnyClockView extends View {

    Paint mCirclePaint;
    float mCircleWidth;

    Paint mDegreePaint;
    float mDegreeWidth;
    float mDegreeLength;

    Paint mPaint;//绘制字

    Paint mHourPaint;
    float mHourWidth;
    float mHourLength;

    Paint mMinPaint;
    float mMinWidth;
    float mMinLength;

    Paint mSecondPaint;
    float mSecondWidth;
    float mSecondLength ;

    Paint mPointPaint;//绘制指针中间的圆点

    float indicatorBackLength;//针后面伸出的长度

    int degreeColor;//刻度及字体颜色

    int hourColor;
    int minColor;
    int secondColor;

    float defaultWidth = 560;
    float defaultHeight = 560;

    int width;//该控件宽高一样

    Context mContext;

    public AnyClockView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mContext = context;

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyClockView);
        if (typedArray != null){
            degreeColor = typedArray.getColor(R.styleable.MyClockView_degreeColor, Color.BLACK);
            hourColor = typedArray.getColor(R.styleable.MyClockView_hourIndicatorColor, Color.BLACK);
            minColor = typedArray.getColor(R.styleable.MyClockView_minIndicatorColor, Color.BLACK);
            secondColor = typedArray.getColor(R.styleable.MyClockView_secondIndicatorColor, Color.BLACK);
        }

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(50);
        mPaint.setStrokeWidth(5);

        mCirclePaint = new Paint();
        mCirclePaint.setStyle(Paint.Style.STROKE);
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setDither(true);
        mCirclePaint.setColor(degreeColor);

        mDegreePaint = new Paint();
        mDegreePaint.setAntiAlias(true);
        mDegreePaint.setDither(true);
        mDegreePaint.setColor(degreeColor);

        mHourPaint = new Paint();
        mHourPaint.setAntiAlias(true);
        mHourPaint.setDither(true);
        mHourPaint.setColor(hourColor);

        mMinPaint = new Paint();
        mMinPaint.setAntiAlias(true);
        mMinPaint.setDither(true);
        mMinPaint.setColor(minColor);

        mSecondPaint = new Paint();
        mSecondPaint.setAntiAlias(true);
        mSecondPaint.setDither(true);
        mSecondPaint.setColor(secondColor);

        mPointPaint = new Paint();
        mPointPaint.setColor(Color.WHITE);
        mPointPaint.setAntiAlias(true);
        mPointPaint.setDither(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mCircleWidth = width/60;

        mSecondLength = (float) (width/2*0.8);
        mSecondWidth = width/100;

        mMinLength = (float) (width/2*0.65);
        mMinWidth = width/80;

        mHourLength = (float) (width/2*0.45);
        mHourWidth = width/50;

        mCirclePaint.setStrokeWidth(mCircleWidth);
        mDegreePaint.setStrokeWidth(mDegreeWidth);
        mHourPaint.setStrokeWidth(mHourWidth);
        mMinPaint.setStrokeWidth(mMinWidth);
        mSecondPaint.setStrokeWidth(mSecondWidth);

        indicatorBackLength = width/16;


        canvas.drawCircle(width/2, width/2, (width-mCircleWidth)/2, mCirclePaint);
        drawDegree(canvas);

        Calendar calendar = Calendar.getInstance();
        drawSecondIndicator(canvas, calendar);
        drawMinIndicator(canvas, calendar);
        drawHourIndicator(canvas, calendar);
        drawCenterPoint(canvas);
        postInvalidateDelayed(1000);
    }

    /**
     * 绘制秒针
     * @param canvas
     */
    private void drawSecondIndicator(Canvas canvas, Calendar calendar) {
        float secondAngle = calendar.get(Calendar.SECOND) / 60f * 360;
        float[] floats = getStartAndEndPointsXY(secondAngle, mSecondLength);
        canvas.drawLine(floats[0], floats[1], floats[2], floats[3], mSecondPaint);
    }

    /**
     * 绘制分针
     * @param canvas
     */
    private void drawMinIndicator(Canvas canvas, Calendar calendar) {
        float minAngle = calendar.get(Calendar.MINUTE) / 60f * 360;
        Log.e("------", minAngle + "");
        float[] floats = getStartAndEndPointsXY(minAngle, mMinLength);
        canvas.drawLine(floats[0], floats[1], floats[2], floats[3], mMinPaint);
    }

    /**
     * 绘制时针
     * @param canvas
     * @param calendar
     */
    private void drawHourIndicator(Canvas canvas, Calendar calendar) {
        float hourAngle = calendar.get(Calendar.HOUR) / 12f * 360 + calendar.get(Calendar.MINUTE)/12f/60*360;
        float[] floats = getStartAndEndPointsXY(hourAngle, mHourLength);
        canvas.drawLine(floats[0], floats[1], floats[2], floats[3], mHourPaint);
    }
    /**
     * 绘制指针交汇的中心点
     * @param canvas
     */
    private void drawCenterPoint(Canvas canvas) {
        canvas.drawCircle(width/2, width/2, 4, mPointPaint);
    }

    /**
     * 根据所在象限及正、余弦定理
     * 获取起点和终点的XY坐标
     * @param angle
     * @param length
     * @return
     */
    private float[] getStartAndEndPointsXY(float angle, float length){
        float[] points = new float[4];//依次是起点x、y，终点x、y坐标组成的数组
        if(angle < 90f){
            points[0] = -(float) Math.sin(angle*Math.PI/180) * indicatorBackLength + width/2;
            points[1] = (float) Math.cos(angle*Math.PI/180) * indicatorBackLength + width/2;
            points[2] = (float) Math.sin(angle*Math.PI/180) * length + width/2;
            points[3] = -(float) Math.cos(angle*Math.PI/180) * length + width/2;
        }else if(angle < 180f){
            points[0] = -(float) Math.cos((angle-90)*Math.PI/180) * indicatorBackLength + width/2;
            points[1] = -(float) Math.sin((angle-90)*Math.PI/180) * indicatorBackLength + width/2;
            points[2] = (float) Math.cos((angle-90)*Math.PI/180) * length + width/2;
            points[3] = (float) Math.sin((angle-90)*Math.PI/180) * length + width/2;
        }else if(angle < 270f){
            points[0] = (float) Math.sin((angle-180)*Math.PI/180) * indicatorBackLength + width/2;
            points[1] = -(float) Math.cos((angle-180)*Math.PI/180) * indicatorBackLength + width/2;
            points[2] = -(float) Math.sin((angle-180)*Math.PI/180) * length + width/2;
            points[3] = (float) Math.cos((angle-180)*Math.PI/180) * length + width/2;
        }else if(angle <= 360f){
            points[0] = (float) Math.cos((angle-270)*Math.PI/180) * indicatorBackLength + width/2;
            points[1] = (float) Math.sin((angle-270)*Math.PI/180) * indicatorBackLength + width/2;
            points[2] = -(float) Math.cos((angle-270)*Math.PI/180) * length + width/2;
            points[3] = -(float) Math.sin((angle-270)*Math.PI/180) * length + width/2;
        }
        return points;
    }

    /**
     * 绘制刻度
     * @param canvas
     */
    private void drawDegree(Canvas canvas) {
        for (int i = 0; i < 60; i++) {
            if (i%15 == 0){
                mDegreeLength = width/16;
                mDegreeWidth = width/50;
                /**
                 * 绘制一个小矩形，使字体在矩形内居中
                 */
                Rect rect = new Rect(width/2-15, 55, width/2+15, 80);
                mPaint.setColor(ContextCompat.getColor(mContext, R.color.color_00ffffff));
                canvas.drawRect(rect, mPaint);
                mPaint.setColor(degreeColor);

                Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
                int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;
                // 下面这行是实现水平居中，drawText对应改为传入targetRect.centerX()
                mPaint.setTextAlign(Paint.Align.CENTER);
                /**
                 * 因为3、6、9绘制出来字体方向不好查看，所以进行以下处理
                 */
                if (i/5 == 9){
                    canvas.rotate(90f, width/2, 67.5f);//为了字体方向竖直，顺时针旋转90°
                    canvas.drawText("9", rect.centerX(), baseline, mPaint);//旋转90°后绘制字
                    canvas.rotate(-90f, width/2, 67.5f);//绘制完该字后，再逆时针旋转回原先的状态
                }else if (i/5 == 6){
                    canvas.drawText("9",rect.centerX(), baseline, mPaint);
                }else if (i/5 == 3){
                    canvas.rotate(-90f, width/2, 67.5f);
                    canvas.drawText("3", rect.centerX(), baseline, mPaint);
                    canvas.rotate(90f, width/2, 67.5f);
                }else {
                    canvas.drawText(i/5 + "",rect.centerX(), baseline, mPaint);
                }
            }else if (i%5 == 0){
                mDegreeLength = width/22;
                mDegreeWidth = width/50;
            }else {
                mDegreeLength = width/30;
                mDegreeWidth = width/75;
            }
            mDegreePaint.setStrokeWidth(mDegreeWidth);
            canvas.drawLine(width/2, 0, width/2, mDegreeLength, mDegreePaint);//绘制当前刻度
            canvas.rotate(360/60f, width/2, width/2);//每次转动一定角度，分60次。一周360°有60个刻度
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.AT_MOST){
            width = (int) defaultWidth;
            setMeasuredDimension((int) defaultWidth, (int) defaultHeight);
        }else {
            width = Math.min(widthSize, heightSize);
            setMeasuredDimension(width, width);
        }
    }
}

